import json
import os
from bs4 import BeautifulSoup
import random
# 导包顺序：python标准库，第三方插件，自己定义的包
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.db.models import Count, F
from django.db.models.functions import TruncMonth
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.views.decorators.cache import cache_page

from WenhahaBlogA import settings
from blogSystem1.MyForms import UserForm
from blogSystem1.models import UserInfo, Article, Category, Tag, ArticleUpDown, Comment
from blogSystem1.utils.validCode import create_valid_code_img


@cache_page(60)
def home(request):
    articles = Article.objects.all()
    data = {
        'title': '博客系统-乐在分享',
        'articles': articles,
    }
    return render(request, 'main/index.html', context=data)


def login(request):
    if request.method == "POST":

        response = {
            'user': None,
            'msg': None,
        }

        username = request.POST.get('username')
        password = request.POST.get('password')
        valid_code = request.POST.get('valid_code')

        valid_code_str = request.session.get('valid_code_str')

        if not valid_code:
            response['msg'] = '请输入验证码！'
        elif not username:
            response['msg'] = '请输入用户名！'
        elif not password:
            response['msg'] = '请输入密码！'

        elif valid_code.upper() == valid_code_str.upper() or valid_code == '666':
            user = auth.authenticate(username=username, password=password)
            if user:
                auth.login(request, user)  # request.user == 当前登陆对象
                response['user'] = user.username
            else:
                response['msg'] = '用户名 或 密码错误!'
        else:
            response['msg'] = '验证码错误!'

        return JsonResponse(response)
    data = {
        'title': '登陆页面',
    }

    return render(request, 'user/login.html', context=data)


def logout(request):
    auth.logout(request)  # 相当于request.session.flush()
    return redirect('/blogsystem/')


def get_validcode_img(request):
    data = create_valid_code_img(request)

    return HttpResponse(data)


# 基于form表单的注册
def register(request):
    if request.is_ajax():
        form = UserForm(request.POST)

        response = {
            'user': None,
            'msg': None,
        }
        if form.is_valid():
            response['user'] = form.cleaned_data.get('user')
            print(form.cleaned_data, response)
            # 生成一条用户记录
            username = form.cleaned_data.get('user')
            password = form.cleaned_data.get('password')
            email = form.cleaned_data.get('email')
            # 注意文件的获取,avatar存的是文件相对路径
            avatar_obj = request.FILES.get('avatar')

            extra = {}
            if avatar_obj:
                extra['avatar'] = avatar_obj
            user_obj = UserInfo.objects.create_user(username=username, password=password, email=email, **extra)

        else:
            response['msg'] = form.errors

        return JsonResponse(response)
    form = UserForm()
    data = {
        'title': '注册页面',
        'form': form,
    }
    return render(request, 'user/register.html', context=data)


def home_site(request, username, **kwargs):
    """
    个人站点视图函数
    :param username: 站点名
    :param request:
    :return:
    """
    # 过滤，保证用户列表里面有该用户站点名
    user = UserInfo.objects.filter(username=username).first()
    # 用户不存在则返回错误页面
    if not user:
        data = {'title': '404 NOT FOUND'}
        return render(request, 'errors/404_not_find.html', context=data)

    # 获取当前站点对象
    blog = user.blog
    # 基于 __
    # articles = Article.objects.filter(user=user)

    # 基于对象查询所有站点文章
    articles = user.article_set.all()
    if kwargs:

        condition = kwargs.get('condition')
        param = kwargs.get('param')
        if condition == 'category':
            articles = articles.filter(user=user).filter(category__title=param)
        elif condition == 'tag':
            articles = articles.filter(user=user).filter(tags__title=param)
        elif condition == 'archive':
            year, month = param.split('-')
            articles = articles.filter(user=user).filter(create_time__year=year).filter(create_time__month=month)

    # 查询每一个分类名称以及对应的文章数
    res = Category.objects.values('pk').annotate(c=Count('article__title')).values('title')

    # 查询当前站点的每一个分类名称以及对应的文章数
    categories = Category.objects.filter(blog=blog).values('pk').annotate(count=Count('article__title')).values_list(
        'title', 'count')
    # print(categories)
    # 查询当前站点的每一个 标签 名称以及对应的文章数
    tags = Tag.objects.filter(blog=blog).values('pk').annotate(count=Count('article')).values_list('title', 'count')
    # print(tags)
    # 查询当前站点每一个年月的名称以及对应的文章数
    # 方式一：
    list_date = Article.objects.filter(user=user).extra(
        select={'y_m_date': 'date_format(create_time,"%%Y-%%m")'}).values('y_m_date').annotate(
        count=Count('nid')).values_list('y_m_date', 'count')
    # print(list_date)
    # 方式二：
    # list_date = Article.objects.filter(user=user).annotate(month=TruncMonth('create_time')).values('month').annotate(count=Count('nid')).values_list('month','count')
    data = {
        'title': username + ' 的博客',
        'username': blog.userinfo.username,
        'blog': blog,
        'articles': articles,
        'categories': categories,
        'tags': tags,
        'list_date': list_date,
    }
    return render(request, 'user/self_site.html', context=data)


def article_site(request, username, article_id):
    user = UserInfo.objects.filter(username=username).first()
    blog = user.blog

    article_obj = Article.objects.filter(pk=article_id).first()

    comments = Comment.objects.filter(article_id=article_id)

    data = {
        'title': username + ' 的博客',
        'username': username,
        'article_obj': article_obj,
        'blog': blog,
        'comments': comments,
    }
    return render(request, 'user/article_site.html', context=data)


def prise_article(request):
    article_id = request.POST.get('article_id')

    is_up = request.POST.get('is_up')
    if is_up == 'true':
        is_up = True
    else:
        is_up = False
    user_id = request.user.pk

    if request.method == 'POST':
        print('p')
    if request.method == 'GET':
        print('g')
    else:
        print('n')

    print(article_id, is_up, user_id, request.method)

    data = {
        'state': True,
        'is_handled': None,
    }

    obj = ArticleUpDown.objects.filter(user_id=user_id, article_id=article_id).first()
    if obj:
        data['state'] = False
        data['is_handled'] = obj.is_up
    else:
        aud = ArticleUpDown.objects.create(article_id=article_id, is_up=is_up, user_id=user_id)
        queryset = Article.objects.filter(pk=article_id)
        if is_up:
            queryset.update(up_count=F('up_count') + 1)
        else:
            queryset.update(down_count=F('down_count') + 1)

    # article.
    return JsonResponse(data)


def commenting(request):
    article_id = request.POST.get('article_id')
    pid = request.POST.get('pid')
    content = request.POST.get('content')
    user_id = request.user.pk

    with transaction.atomic():
        com_obj = Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid)
        Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)

    response = {
        "create_time": com_obj.create_time.strftime("%Y-%m-%d %X"),
        "username": request.user.username,
        "content": content,
        "pid": pid,
    }

    return JsonResponse(response)


def get_comment_tree(request):
    article_id = request.GET.get('article_id')
    ret = list(
        Comment.objects.filter(article_id=article_id).order_by('pk').values('pk', 'content', 'parent_comment_id'))

    # ret是一个列表，作为json格式的数据返回时要注意关键字参数safe=False
    return JsonResponse(ret, safe=False)


@login_required
def cn_backend(request):
    article_list = Article.objects.filter(user=request.user)
    title = '后台管理'
    return render(request, 'backend/backend.html', locals())


@login_required
def add_article(request):
    if request.method == "POST":
        title = request.POST.get('title')
        content = request.POST.get('content')

        soup = BeautifulSoup(content, 'html.parser')

        # 过滤script，简单防止xss攻击
        for tag in soup.find_all():
            if tag.name == 'script':
                tag.decompose()

        desc = soup.text[0:150]
        print(soup)

        Article.objects.create(title=title, content=str(soup), user=request.user, desc=desc)
        return redirect('blogsystem:cn_backend')
    title = '增加文章'
    return render(request, 'backend/add_article.html', locals())


def upload_img_add_article(request):
    img = request.FILES.get('img_article')

    path = os.path.join(settings.MEDIA_ROOT, "img_add_article", img.name)
    with open(path, 'wb') as f:
        for line in img:
            f.write(line)

    response = {
        'error': 0,
        'url': '/media/img_add_article/%s' % img.name,
    }
    return HttpResponse(json.dumps(response))


@login_required()
def article_delete(request, article_id):
    article = Article.objects.filter(pk=article_id).first()
    article.delete()
    return redirect('blogsystem:cn_backend')
